import importlib
import operator
from functools import reduce

import pandas as pd
import requests
from django.db.models import Q

from Dify.serializers import *

from DifyDjango.settings import ROOT_URL

import re
from datetime import datetime
from django.apps import apps


# 修改单据审核状态
def updateOrderExamineStatus(order, data):
    if data.get('pay_status'):
        order['pay_status'] = data['pay_status']
    else:
        order['pay_status'] = 0
    if data.get('cost_data'):
        order['cost_data'] = data['cost_data']
    else:
        order['cost_data'] = None
    order['examine_status'] = 0
    order['examine_time'] = None
    order['examine_id'] = None
    if data.get('user_id'):
        order['preparation_id'] = data['user_id']
        order['operation_id'] = data['user_id']
    order['operation_time'] = time.time()
    order['create_time'] = time.time()
    order['update_time'] = time.time()
    return order


# 设置单据批次状态
def updateOrderBatchStatus(order, data):
    keys = ['batch_id', 'batch_name', 'manufacture', 'guarantee', 'validity', 'period']
    for key in keys:
        order[key] = None
    for key, value in data.items():
        if key in keys:
            order[key] = value
    return order


# 设置字典空字符串为None并且处理时间格式
def setDictNone(data):
    time_patterns = [
        # 完整日期时间格式
        r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$',  # YYYY-MM-DD HH:MM:SS
        r'^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}$',  # YYYY/MM/DD HH:MM:SS
        r'^\d{4}年\d{2}月\d{2}日 \d{2}时\d{2}分\d{2}秒$',  # 中文格式
        # 仅日期格式
        r'^\d{4}-\d{2}-\d{2}$',  # YYYY-MM-DD
        r'^\d{4}/\d{2}/\d{2}$',  # YYYY/MM/DD
        r'^\d{4}年\d{2}月\d{2}日$'  # 中文日期
    ]

    def process_value(value):
        if isinstance(value, dict):
            return setDictNone(value)  # 递归处理字典
        elif isinstance(value, list):
            return [process_value(item) for item in value]  # 递归处理列表
        elif isinstance(value, str):
            if value == '':
                return None
            if any(re.match(pattern, value) for pattern in time_patterns):
                normalized_str = (
                    value.replace('年', '-').replace('月', '-').replace('日', '')
                    .replace('时', ':').replace('分', ':').replace('秒', '')
                )
                try:
                    # 尝试解析完整日期时间
                    dt = datetime.strptime(normalized_str, "%Y-%m-%d %H:%M:%S")
                except ValueError:
                    try:
                        # 尝试解析仅日期
                        dt = datetime.strptime(normalized_str, "%Y-%m-%d")
                    except ValueError:
                        return value  # 如果都不匹配，返回原值
                return int(dt.timestamp())
        return value  # 非字符串或无需处理的值直接返回

    if isinstance(data, dict):
        return {key: process_value(value) for key, value in data.items()}
    elif isinstance(data, list):
        return [process_value(item) for item in data]
    else:
        return data  # 非字典/列表直接返回


# 根据商品名称或编号查询商品信息
def getGoodsInfoByCodeOrName(data):
    if 'goods_name' not in data.keys() and 'goods_code' not in data.keys():
        return False, "请输入商品名称或编号"

    goods = FaKuyouGoods.objects.filter(
        Q(goods_code=data.get('goods_code', None)) | Q(goods_name=data.get('goods_name', None))).first()
    if not goods:
        return False, "商品不存在"

    goods_serializer = FaKuyouGoodsSerializer(goods)
    return True, goods_serializer.data


# 根据商品名称或编号查询库存信息
def getGoodsStockInfoByCodeOrName(data):
    goods = getGoodsInfoByCodeOrName(data)
    if not goods[0]:
        return False, goods[1], 0
    goods = goods[1]
    # 查询仓库是否存在
    if data.get('store'):
        store = FaKuyouStores.objects.filter(Q(name=data['store']) | Q(id=data['store'])).first()
        if not store:
            return False, "仓库不存在", 0
        # 查询仓库库存
        stock = FaKuyouGoodsStock.objects.filter(goods_id=goods.get("id"), stores_id=store.id).first()
    else:
        # 查询默认仓库库存
        stock = FaKuyouGoodsStock.objects.filter(goods_id=goods.get("id"),
                                                 stores_id=goods.get('manager_warehouse_id')).first()
        store = FaKuyouStores.objects.filter(id=goods.get('manager_warehouse_id')).first()
    if not stock:
        return True, 0, store.id
    return True, stock.stock, store.id


# 根据供应商名称或编号查询供应商信息
def getSupplierInfoByCodeOrName(data):
    if 'supplyer_name' not in data.keys() and 'supplyer_code' not in data.keys():
        return False, "请输入供应商名称或编号"
    supplier = FaKuyouSuppliers.objects.filter(
        Q(supplyer_code=data.get('supplyer_code', None)) | Q(supplyer_name=data.get('supplyer_name', None))).first()
    if not supplier:
        return False, "供应商不存在"
    return True, supplier


# 导出excel表格
def getExcelByMarkdown(md, md_name):
    """
    将 Markdown 文件中的表格转换为 Excel 文件

    参数:
        md_file_path (str): Markdown 文件路径
        excel_file_path (str, optional): 输出的 Excel 文件路径。如果为 None，则使用与输入文件相同的路径，扩展名改为 .xlsx

    返回:
        str: 生成的 Excel 文件路径
    """
    try:
        lines = [line.strip() for line in md.split('\n') if line.strip()]
        headers = [h.strip() for h in re.split(r'\s*\|\s*', lines[0])[1:-1]]
        data = []
        for line in lines[2:]:  # 跳过标题行和分隔线
            data.append([d.strip() for d in re.split(r'\s*\|\s*', line)[1:-1]])

        # 创建 DataFrame
        df = pd.DataFrame(data, columns=headers)
        file_name = f'{md_name}_{datetime.now().strftime("%Y_%m_%d_%H_%M")}.xlsx'
        file_path = f'D:\www\DifyDjango\excel\{file_name}'

        # 保存为 Excel
        df.to_excel(file_path, index=False, encoding='utf-8')
        return True, file_name
    except Exception as e:
        return False, str(e)


# 处理外键关联字段
def handleForeignKey(data):
    # 定义外键字段列表及其对应的处理方式
    FOREIGN_KEY_MAPPING = {
        'manager_warehouse_id': (FaKuyouStores, FaKuyouStoresSerializer, 'name', 'id', 1),
        'unit_id': (FaKuyouUnit, FaKuyouUnitSerializer, 'name', 'id', 1),
        'customers_id': (FaKuyouCustomer, FaKuyouCustomerSerializer, 'customer_name', 'id', 1),
        'goods_unit': (FaKuyouUnit, FaKuyouUnitSerializer, 'name', 'id', 1),
        'stores_id': (FaKuyouStores, FaKuyouStoresSerializer, 'name', 'id', 1),
        'sale_user': (FaKuyouStaffMember, FaKuyouStaffMemberSerializer, 'name', 'id', 1),
        'preparation_id': (FaAdmin, FaAdminSerializer, 'nickname', 'id', 1),
        'operation_id': (FaAdmin, FaAdminSerializer, 'nickname', 'id', 1),
        'examine_id': (FaAdmin, FaAdminSerializer, 'nickname', 'id', 1),
        'workshop_id': (FaKuyouWorkshop, FaKuyouWorkshopSerializer, 'name', 'id', 1),
        'work_id': (FaKuyouStaffMember, FaKuyouStaffMemberSerializer, 'name', 'id', 1),
        'supplyer_code': (FaKuyouSuppliers, FaKuyouSuppliersSerializer, 'supplyer_name', 'supplyer_code', 0),
        'goods_code': (FaKuyouGoods, FaKuyouGoodsSerializer, 'goods_name', 'goods_code', 0),
        'goods_type_id': (FaKuyouGoodsType, FaKuyouGoodsTypeSerializer, 'supplier_type_name', 'id', 1),
        'goods_image': (FaKuyouGoods, FaKuyouGoodsSerializer, 'goods_image', 'goods_image', 2),
        'customertype_id': (FaKuyouCustomerType, FaKuyouCustomerTypeSerializer, 'type_name', 'id', 1),
        'customerlevel_id': (FaKuyouCustomerLevel, FaKuyouCustomerLevelSerializer, 'name', 'id', 1),
        'staff_member_id': (FaKuyouStaffMember, FaKuyouStaffMemberSerializer, 'name', 'id', 1),
        'default_unit': (FaKuyouUnit, FaKuyouUnitSerializer, 'name', 'id', 1),
        'suppliers_id': (FaKuyouSuppliers, FaKuyouSuppliersSerializer, 'supplyer_name', 'id', 1),
        # 'business_type': (FaKuyouAccountsReceivable, "ReceivableSerializer", 'business_type', 'business_type', 2),

    }

    def replace_ids_with_names(model_class, serializer_class, name_field, rows, column_index, key, is_replace):
        # 修改分类名称
        # if is_replace == 2:
        #     for row in rows[1:]:
        #         row[column_index] = model_class.get_type(model_class, row[column_index])
        # else:
        """替换ID为名称的通用函数"""
        # 批量查询所有相关对象
        query = reduce(operator.or_, [Q(**{f"{key}": row[column_index]}) for row in rows[1:]])
        queryset = model_class.objects.filter(query).values(key, name_field)

        # 创建ID到名称的映射字典
        id_to_name = {item[key]: item[name_field] for item in queryset}

        # 在数据中新增名称列或替换原列
        for row in rows[1:]:
            if row[column_index] in id_to_name:
                value = id_to_name[row[column_index]]
                if is_replace == 1:
                    row[column_index] = value
                elif is_replace == 2 and name_field == 'goods_image':
                    # 拼接前缀URL
                    row[column_index] = f"https://cellplay.klry.com.cn/{value}"
                else:
                    row.append(value)
            else:
                if is_replace == 1:
                    row[column_index] = None
                else:
                    row.append(None)  # 如果没有找到对应的名称，新增None

        # 处理每个数据项
    for sheet_name, sheet_data in data.items():
        headers = sheet_data[0]  # 第一行是表头
        # 找出需要处理的外键列
        for col_index, field_name in enumerate(headers):
            if field_name in FOREIGN_KEY_MAPPING:
                model_class, serializer_class, name_field, key, is_replace = FOREIGN_KEY_MAPPING[field_name]
                replace_ids_with_names(model_class, serializer_class, name_field, sheet_data, col_index, key,
                                       is_replace)
                if is_replace == 0:
                    headers.append('_'.join(field_name.split('_')[:-1]) + '_name')

    return data


# 加载所有模型
def load_models_from_module():
    """
    加载指定模块下的所有模型类，缓存到字典中
    """
    from django.db.models import Model
    models_cache = {}
    model_file_list = ["admin", "BOM", "goods", "member", "other", "production", "purchase", "sales", "stock",
                       "workshop"]
    for model_file in model_file_list:
        module = importlib.import_module(f'Dify.models.{model_file}')
        for attr_name in dir(module):
            attr = getattr(module, attr_name)
            if isinstance(attr, type) and issubclass(attr, Model) and attr is not Model:
                models_cache[attr_name] = attr
    return models_cache


# 下划线转大驼峰命名
def to_camel_case(snake_str):
    """
    将下划线命名（a_b_c）转换为大驼峰命名（A_B_C -> ABc）
    """
    components = snake_str.split('_')
    # 每个单词首字母大写，拼接
    return ''.join(x.title() for x in components)


# 获取单号
def getOrderCode(doc_type, current_number=None):
    """
    生成单据编号
    :param doc_type: 单据类型（数字）
    :param current_number: 当前编号（可选）
    :return: 新编号
    """
    try:
        # 获取编号配置
        prefix_config = FaKuyouPrefix.objects.get(type=doc_type)
    except FaKuyouPrefix.DoesNotExist:
        raise ValueError(f"未找到类型为 {doc_type} 的编号配置")

    # 提取当前编号中的数字部分
    if current_number:
        numbers = re.findall(r'\d+', current_number)
        order_num = int(numbers[0][-3:]) if numbers else 0
    else:
        order_num = 0

    # 确定新的数字部分
    if order_num < prefix_config.start:
        order_num = prefix_config.start
    else:
        order_num += 1

    # 构建前缀
    prefix = prefix_config.prefix
    if prefix_config.year == "1":
        prefix += datetime.now().strftime('%Y')
    if prefix_config.month == "1":
        prefix += datetime.now().strftime('%m')
    if prefix_config.day == "1":
        prefix += datetime.now().strftime('%d')
    if prefix_config.hour == "1":
        prefix += datetime.now().strftime('%H')
    if prefix_config.minute == "1":
        prefix += datetime.now().strftime('%M')
    if prefix_config.second == "1":
        prefix += datetime.now().strftime('%S')

    # 补零
    number_str = str(order_num).zfill(prefix_config.strlen)
    new_number = f"{prefix}{number_str}"

    # 检查编号唯一性
    if prefix_config.dbname and prefix_config.field:
        models = load_models_from_module()
        if models.get("Fa" + to_camel_case(prefix_config.dbname)).objects.filter(
                **{prefix_config.field: new_number}).exists():
            # 如果编号已存在，递归生成新编号
            return getOrderCode(doc_type, new_number)

    return new_number


# 费用构建
def getDataCost(data):
    def str_len(s):
        return len(s.encode('utf-8'))

    result = f"a:{len(data)}:{{"  # 外层字典大小
    # 采购费用总和
    purchase_money = 0
    for i, item in enumerate(data):
        # 获取供应商信息
        supplyer = getSupplierInfoByCodeOrName(item)
        if not supplyer[0]:
            return False, supplyer[1]
        suppliers_id = supplyer[1].id
        expend_type = FaKuyouExpendType.objects.filter(name=item.get('expend_type', None)).first()
        if not expend_type:
            return False, "支出类别不存在"
        expend_type_id = expend_type.id
        money = item.get("money", "")
        remark = item.get("remark", "")
        purchase_money += money
        # 构造内层字典字符串
        inner_dict = (
            f"s:{str_len('suppliers_id')}:\"suppliers_id\";"
            f"s:{str_len(str(suppliers_id))}:\"{suppliers_id}\";"
            f"s:{str_len('expend_type_id')}:\"expend_type_id\";"
            f"s:{str_len(str(expend_type_id))}:\"{expend_type_id}\";"
            f"s:{str_len('money')}:\"money\";"
            f"s:{str_len(str(money))}:\"{money}\";"
            f"s:{str_len('remark')}:\"remark\";"
            f"s:{str_len(str(remark))}:\"{remark}\";"
        )
        result += f"i:{i};a:4:{{{inner_dict}}}"
    result += "}"
    return result, purchase_money
